package cn.wolfcode.luowowo.search.serevice.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.IStrategySearchRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.ESStatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class StrategyTemplateServiceImpl implements IStrategyTemplateService {
    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private IStrategySearchRepository repository;

    @Autowired
    private ElasticsearchClient client;

    @Override
    public void save(StrategyTemplate t) {
        repository.save(t);
    }

    @Override
    public List<Map<String, Object>> getThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();
        //查询所有的主题  需要利用分组去重
        List<ESStatisVO> list = getStatisVo("themeId", "themeName", ESStatisVO.THEME_STATIS_SEARCH);
        //分组查询   有2 个   themeId   themeName
        //查前10个
        List<ESStatisVO> subList ;
        if (list.size() > 10) {
            subList = list.subList(0, 10);
        } else {
            subList = list.subList(0, list.size());
        }

        for (ESStatisVO theme : subList) {
            Map<String, Object> map = new HashMap<>();
            //添加左侧主题
            map.put("theme", theme);
            List<ESStatisVO> dests = this.getDestByThemeId(theme.getId());
            //添加右侧目的地
            map.put("dests",dests);
            //封装成一个对象
            data.add(map);
        }
        return data;
    }

    @Override
    public List<ESStatisVO> getStatisVo(String idName,String GroupName,int type) {

        //分组查询   有2 个   themeId   themeName
        List<CompositeValuesSourceBuilder<?>> source = new ArrayList<>();

        //按照themeId进行分组
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.missingBucket(true);
        idSource.field(idName);
        source.add(idSource);

        //按照themeName进行分组
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        idSource.missingBucket(true);
        nameSource.field(GroupName);
        source.add(nameSource);

        //组合分组查询   将2个分组源加入分组当中
        CompositeAggregationBuilder aggsBulider = new CompositeAggregationBuilder("themeGroup",source);

        //基本的查询builder   添加索引和类型   加入分组的aggs
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggsBulider);
        builder.withIndices("luowowo_strategy");
        builder.withTypes("strategy");

        QueryBuilder query = null;
        //国内攻略
        if (type == ESStatisVO.INLAND_STATIS_SEARCH) {
            query = QueryBuilders.termQuery("countryId", 1);
        }
        //国外攻略把中国删除
        if (type == ESStatisVO.ABROAD_STATIS_SEARCH) {
            query = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));
        }
        builder.withQuery(query);

        //开始查询   需要得到aggs类型  所以类型不能是page  一些方法在具体的实现类中
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        InternalComposite aggs = page.getAggregations().get("themeGroup");

        //遍历所有的桶  得到每一个主题id 和name  ----->通过id去查询目的地
        List<ESStatisVO> list = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : aggs.getBuckets()) {
            Map<String, Object> key = bucket.getKey();
            ESStatisVO theme = new ESStatisVO();
            long id = Long.parseLong(key.get("id").toString());
            theme.setId(id);
            theme.setName(key.get("name").toString());
            theme.setCount(bucket.getDocCount());
            list.add(theme);
        }

        //排序
        list.sort((o1,o2)->
                (int) (o2.getCount()-o1.getCount())
        );
        return list;
    }


    @Override
    public Page queryBytype(SearchQueryObject qo) {
        String option = null;
        if (qo.getType() == null || qo.getType() == -1) {
            return repository.findAll(PageRequest.of(qo.getCurrentPage() - 1,
                    qo.getPageSize(), Sort.by(Sort.Direction.DESC, qo.getOrderBy())));
        }
        if (qo.getType() == ESStatisVO.INLAND_STATIS_SEARCH) {
            option = "destId";
        } else if (qo.getType() == ESStatisVO.ABROAD_STATIS_SEARCH) {
            option = "countryId";
        } else if (qo.getType() == ESStatisVO.THEME_STATIS_SEARCH) {
            option = "themeId";
        }

        QueryBuilder query = null;
        if (qo.getType() != -1) {
             query = QueryBuilders.termQuery(option,qo.getTypeValue());
        }
        return repository.search(query, PageRequest.of(qo.getCurrentPage() - 1,
                qo.getPageSize(), Sort.by(Sort.Direction.DESC, qo.getOrderBy())));
    }

    @Override
    public List<StrategyTemplate> findByDestId(Long id) {
        return repository.findByDestId(id);
    }

    //通过themeid获取目的地
    private List<ESStatisVO> getDestByThemeId(long id) {
        Iterable<StrategyTemplate> dests = repository.search(QueryBuilders.termQuery("themeId", id));
        List<ESStatisVO> list = new ArrayList<>();
        List<String> temp = new ArrayList<>();
        for (StrategyTemplate dest : dests) {
            ESStatisVO vo = new ESStatisVO();
            vo.setId(dest.getId());
            vo.setName(dest.getDestName());
            //去重
            if (!temp.contains(dest.getDestName())) {
                list.add(vo);
            }
            temp.add(dest.getDestName());
        }
        return list;
    }
}
